import routerLink from "./components/routerLink";
import routerView from "./components/routerView";
import { createMatch } from "./createMatch.js";
import BrowserHistory from "./history/BrowserHistory";
import HashHistory from "./history/HashHistory";
export default class VueRouter {
  constructor(option = {}) {
    // vue-router 核心 match
    // 创建映射表
    this.matcher = createMatch(option.routes || []);
    this.beforeHooks = []
    let mode = option.mode || "hash";
    switch (mode) {
      case "hash":
        this.history = new HashHistory(this);
        break;
      case "history":
        this.history = new BrowserHistory(this);
        break;
      default:
        console.warn("没有匹配到mode", mode);
    }
    // console.log("this.history", this.history);
  }
  listen(router) {
    return router;
  }
  init(app) {
    let history = this.history;
    // 根据路径的变化匹配对应的组件进行渲染 视图更新
    // 路径跳转+监控
    history.transitionTo(history.getCurrentLocation(), () => {
      history.setupListeners();
    });
    // 把这方法给listen传递过去 等待更新的时候进行更新
    history.listen((newRoute) => {
      app._route = newRoute;
    });
  }
  // 路由跳转
  push(location) {
    this.history.push(location);
    // this.history.transitionTo(location, () => {
    //   window.location.hash = location;
    // });
  }
  match(location) {
    return this.matcher.match(location);
  }
  beforeEach(cb) {
    this.beforeHooks.push(cb);
  }
}
let Vue;
// 如果要使用vue.use加载必须要有install方法
VueRouter.install = (_vue) => {
  Vue = _vue;
  // 4解决全局组件
  // 4.1加载默认的router-link
  Vue.component("router-link", routerLink);
  // 4.2加载默认的router-view
  Vue.component("router-view", routerView);
  // 5.给每个组件添加router实例
  // Vue.mixin 是 Vue.js 提供的一个全局 API，用于将选项混入 Vue 构造器的选项中。
  // 通过使用 Vue.mixin，你可以将一些配置（如生命周期钩子、方法、属性等）应用到所有 Vue 实例中，从而避免重复代码。
  // 内部通过mergeOptions来实现把对象进行合并
  Vue.mixin({
    // 初始化阶段设置他的router
    beforeCreate() {
      // 渲染是从父到子的
      if (this.$options.router) {
        this._routerRoot = this;
        this._router = this.$options.router;
        this._router.init(this); // 初始化路由
        // 定义响应式数据
        Vue.util.defineReactive(this, "_route", this._router.history.current);
        // console.log("this._routerRoot", this);
        
      } else {
        // 在所有组件实例上增加一个父组件_routerRoot实例  指向根实例
        // console.log(" this.$parent3", this.$parent._router);
        this._routerRoot = this.$parent && this.$parent._routerRoot;
      }
    },
  });
  // 根据组件实例获取router实例
  Object.defineProperty(Vue.prototype, "$router", {
    get() {
      return this._routerRoot && this._routerRoot._router;
    },
  });
  Object.defineProperty(Vue.prototype, "$route", {
    get() {
      return this._routerRoot && this._routerRoot._route;
    },
  });
};
